package core

import (
	"bytes"
	"encoding/json"
	"log"
	"reflect"
	"sort"
	"strconv"
	"strings"
)

type LuaBuilder struct {
}

func (builder *LuaBuilder) BuildHeadInfo(row []string, headFix [2]string) *HeadInfo {
	return buildLuaOrJson(row, headFix)
}
func (builder *LuaBuilder) GetSaveFileName(fileName string) string {
	if strings.HasSuffix(fileName, LuaFileNameFix) {
		return fileName
	} else {
		return fileName + LuaFileNameFix
	}
}
func (builder *LuaBuilder) BuildHeadLine(exportString *bytes.Buffer, saveFileName string, headInfo *HeadInfo) {
	index := strings.LastIndex(saveFileName, ".")
	if index > 0 {
		saveFileName = saveFileName[index:]
	}
	exportString.WriteString(saveFileName)
	exportString.WriteString(" = {\n")
}
func (builder *LuaBuilder) BuildEnd(exportString *bytes.Buffer, headInfo *HeadInfo) {
	exportString.WriteString("};\n")
}
func (builder *LuaBuilder) GetID(row []string, headInfo *HeadInfo) string {
	idheadItem := headInfo.GetItemByType(LuaIdxName)
	if idheadItem != nil {
		return row[idheadItem.Ix]
	}
	return ""
}
func (builder *LuaBuilder) BuildLine(buffer *bytes.Buffer, info *HeadInfo, id string, row []string) {
	var size = len(info.Items)
	if size == 0 {
		return
	}
	buffer.WriteString("\t")
	haveID := "" != id
	if haveID {
		buffer.WriteString("[" + id + "] = ")
	}
	// buildStart
	buffer.WriteString("{")
	if haveID {
		//--
		buffer.WriteString("id = " + id + ", ")
	}

	for _, item := range info.Items {
		if LuaIdxName == item.Typ {
			continue
		}
		luaBuildLineItem(row, item.Ix, item, buffer)
	}
	buffer.Truncate(buffer.Len() - 2)

	// BuildEnd
	buffer.WriteString("}")

	buffer.WriteString(";\n")
}
func luaBuildLineItem(row []string, k int, item *HeadItem, buffer *bytes.Buffer) {
	cellVal := row[k]
	if len(cellVal) > 0 {
		if strings.Contains(item.Typ, "json") {
			// 校验json格式
			buffer.WriteString(item.FiledName + " = ")

			var dat interface{}
			e := json.Unmarshal([]byte(cellVal), &dat)
			if e == nil {
				readObj2Lua(buffer, dat)
			} else {
				log.Fatal("json解析出错:" + cellVal)
			}
			buffer.WriteString(", ")
		} else {
			buffer.WriteString(item.FiledName)
			buffer.WriteString(" = ")
			switch strings.ToLower(item.Typ) {
			case "str", "strs":
				buffer.WriteString("\"")
				buffer.WriteString(cellVal)
				buffer.WriteString("\"")
				break
			case "bool":
				parseBool(cellVal, buffer)
				break
			case "num", "int":
				parseNum(cellVal, buffer)
			default:
				buffer.WriteString(cellVal)
			}
			buffer.WriteString(", ")
		}
	}
}

func readObj2Lua(buffer *bytes.Buffer, data interface{}) {
	switch data.(type) {
	case []interface{}:
		buffer.WriteString("{")
		readList(buffer, data.([]interface{}))
		buffer.WriteString("}")
		break
	case map[string]interface{}:
		d := data.(map[string]interface{})
		var keys []string
		for k := range d {
			keys = append(keys, k)
		}
		sort.Strings(keys)

		buffer.WriteString("{")
		var idx int
		for _, k := range keys {
			v := d[k]
			idx++
			_, e := strconv.Atoi(k)
			if nil == e {
				buffer.WriteString("[")
				buffer.WriteString(k)
				buffer.WriteString("]")
			} else {
				buffer.WriteString(k)
			}
			buffer.WriteString(" = ")

			switch v.(type) {
			case string:
				buffer.WriteString("'")
				buffer.WriteString(v.(string))
				buffer.WriteString("'")
				break
			case bool:
				buffer.WriteString(strconv.FormatBool(v.(bool)))
				break
			case float64:
				buffer.WriteString(strconv.Itoa(int(v.(float64))))
				break
			default:
				readObj2Lua(buffer, v)
				break
			}
			if idx < len(d) {
				buffer.WriteString(", ")
			}
		}
		buffer.WriteString("}")
		break
	case float64:
		// json 全部转换成数字 float64
		buffer.WriteString(strconv.Itoa(int(data.(float64))))
	default:
		typeOf := reflect.TypeOf(data)
		value := reflect.ValueOf(data)
		println(typeOf)
		println(value.String())
		break
	}

}
func readList(buffer *bytes.Buffer, data []interface{}) {
	for k, v := range data {
		readObj2Lua(buffer, v)
		if k < len(data)-1 {
			buffer.WriteString(",")
		}
	}
}
